namespace SharePoint.ImportExport.Core
{
    using System;
    using System.IO;

    /// <summary>
    /// This enum controls what will be logged
    /// </summary>
    public enum ErrorLevel
    {
        /// <summary>
        /// This information will not be logged
        /// </summary>
        NoLog = -2,

        /// <summary>
        /// The information will be logged to the log file
        /// </summary>
        File = -1,

        /// <summary>
        /// Informative log info, not an error
        /// </summary>
        Information = 0,

        /// <summary>
        /// Logged as a warning
        /// </summary>
        Warning = 1,

        /// <summary>
        /// Logged as an error
        /// </summary>
        Error = 2,

        /// <summary>
        /// Progress information written to the UI
        /// </summary>
        Progress = 3
    }

    /// <summary>
    /// Initializes a new instance of the SPEventArgs class.
    /// </summary>
    public class SPEventArgs : EventArgs
    {
        /// <summary>
        /// This is the internal reporting threshold
        /// </summary>
        private ErrorLevel level;

        /// <summary>
        /// This is the error message
        /// </summary>
        private string message;

        /// <summary>
        /// Initializes a new instance of the SPEventArgs class
        /// </summary>
        /// <param name="level">This is the error level that functions as a threshhold for the logging</param>
        /// <param name="message">This is the message that will be logged</param>
        public SPEventArgs(ErrorLevel level, string message)
        {
            this.level = level;
            this.message = message;
        }

        /// <summary>
        /// Gets the threshold for error reporting
        /// </summary>
        public ErrorLevel Level
        {
            get
            {
                return this.level;
            }
        }

        /// <summary>
        /// Gets the error message
        /// </summary>
        public string Message
        {
            get
            {
                return this.message;
            }
        }
    }

    /// <summary>
    /// This is the helper class for logging
    /// </summary>
    public class Logger
    {
        /// <summary>
        /// This is the actual log file on disk
        /// </summary>
        private static TextWriter logFile = null;

        /// <summary>
        /// Boolean flag indicating if the class was initialized
        /// </summary>
        private static bool isInitialized = false;

        /// <summary>
        /// This is the last error that was logged
        /// </summary>
        private static string internalLastError = String.Empty;

        /// <summary>
        /// This is the log filename
        /// </summary>
        private static string logFileName = String.Empty;

        /// <summary>
        /// This is the threshold for error reporting
        /// </summary>
        private static ErrorLevel reportLevel = ErrorLevel.Information;

        /// <summary>
        /// Finalizes an instance of the Logger class.
        /// </summary>
        ~Logger()
        {
            if (null != logFile)
            {
                logFile.Flush();
                logFile.Close();
            }
        }

        /// <summary>
        /// The is the delegate for calling into the calling process
        /// </summary>
        /// <param name="sender">This is the raiser of the event</param>
        /// <param name="e">This is the argument passed</param>
        public delegate void LogDataEventHandler(object sender, SPEventArgs e);

        /// <summary>
        /// This the the event to be raised
        /// </summary>
        public static event LogDataEventHandler LogDataSendingEvent = null;

        /// <summary>
        /// Gets the last logged error
        /// </summary>
        public static string LastError
        {
            get
            {
                return internalLastError;
            }
        }

        /// <summary>
        /// Gets the filename of the log file
        /// </summary>
        public static string FileName
        {
            get
            {
                return logFileName;
            }
        }

        /// <summary>
        /// Closes the log file
        /// </summary>
        public static void Close()
        {
            try
            {
                logFile.Flush();
            }
            finally
            {
                if (null != logFile)
                {
                    logFile.Close();
                }

                logFile = null;
            }
        }

        /// <summary>
        /// This method writes a string to the logfile
        /// </summary>
        /// <param name="level">This is the errorlevel threshold. The error will only be logged if it has a higher value than the reporting threshold</param>
        /// <param name="logInfo">This is the logged error message</param>
        public static void Log(ErrorLevel level, string logInfo)
        {
            if (level == ErrorLevel.NoLog)
            {
                return;
            }

            if (isInitialized)
            {
                logFile.WriteLine(logInfo);
                logFile.Flush();
            }

            ////Report to the screen only those errors that pass the threshold
            if (level >= reportLevel)
            {
                if (LogDataSendingEvent != null)
                {
                    SPEventArgs args = new SPEventArgs(level, level.ToString() + "-" + logInfo);
                    LogDataSendingEvent(null, args);
                }
            }

            System.Diagnostics.Debug.WriteLine(logInfo);
            internalLastError = logInfo;
        }

        /// <summary>
        /// This method initializes the logfile specified by the parameter
        /// </summary>
        /// <param name="inFileName">This is the filename</param>
        /// <param name="level">This is the errorlevel for the reporting</param>
        public static void Init(string inFileName, ErrorLevel level)
        {
            try
            {
                logFileName = inFileName;
                logFile = File.CreateText(inFileName);
                isInitialized = true;
                reportLevel = level;
            }
            catch (IOException exception)
            {
                System.Diagnostics.Debug.WriteLine("Could not open the file: " + inFileName + ". Error: " + exception.Message);
            }
        }
    }
}
